//
//  ADNavigationManager.m
//  Anda_Driver_Pro
//
//  Created by AnDa-Y on 2019/6/18.
//  Copyright © 2019 AnDa-Y. All rights reserved.
//

#import "ADMANaviManager.h"
//#import "SpeechSynthesizer.h"
#import "ADLocationModel.h"

#define kNaviManagerSelf [ADNavigationManager sharedManager]

@interface ADMANaviManager ()<AMapNaviDriveManagerDelegate, AMapNaviDriveDataRepresentable>
@property (assign, nonatomic) NSInteger naviStrategy;
@property (weak, nonatomic) AMapNaviDriveView *driveView;

//@property (strong, nonatomic) YYTimer *naviCheckTimer;
@property (assign, nonatomic) NSInteger naviLocationNotUpdateCount;
@property (assign, nonatomic) NSInteger badAccracyCount;
@property (assign, nonatomic) NSInteger badAccracyRetryCount;
@end


@implementation ADMANaviManager

@synthesize delegate, isSimulateNav, navigationStatus;

- (void)setupStrategy:(NSInteger)strategy
{
    self.naviStrategy = strategy;
}

- (void)addDriveView:(ADNaviDriveView *)driveView
{
    self.driveView = driveView.aDriveView;
    [[AMapNaviDriveManager sharedInstance] addDataRepresentative:driveView.aDriveView];
}

- (void)removeDriveView:(ADNaviDriveView *)driveView
{
    self.driveView = nil;
    [[AMapNaviDriveManager sharedInstance] removeDataRepresentative:driveView.aDriveView];
}

- (void)startNavigationFrom:(CLLocationCoordinate2D)aLoc toB:(CLLocationCoordinate2D)bLoc
{
    AMapNaviPoint *startPoint = [AMapNaviPoint locationWithLatitude:aLoc.latitude longitude:aLoc.longitude];
    AMapNaviPoint *endPoint = [AMapNaviPoint locationWithLatitude:bLoc.latitude longitude:bLoc.longitude];
    
    [[AMapNaviDriveManager sharedInstance] setDelegate:self];
    [[AMapNaviDriveManager sharedInstance] addDataRepresentative:self];
    
//    [self.naviCheckTimer invalidate];
//    self.naviCheckTimer = nil;
//    self.naviCheckTimer = [YYTimer timerWithTimeInterval:10 target:self selector:@selector(naviCheckTimerAction:) repeats:YES];
    
    [[AMapNaviDriveManager sharedInstance] calculateDriveRouteWithStartPoints:@[startPoint]
                                                                    endPoints:@[endPoint]
                                                                    wayPoints:nil
                                                              drivingStrategy:self.naviStrategy];
}

//导航检查计时器回调
//- (void)naviCheckTimerAction:(YYTimer *)timer
//{
//    self.naviLocationNotUpdateCount += 10;
//
//    if (self.naviLocationNotUpdateCount > kNaviPointAllowNotUpdateTime) {//超过允许点不更新的时间
//        self.badAccracyRetryCount++;
//        if (self.badAccracyRetryCount < kBadAccuracyPointRetryCount) {//未超过允许重试的次数
//            [[AMapNaviDriveManager sharedInstance] recalculateDriveRouteWithDrivingStrategy:self.naviStrategy];
//        }else{//超过重试次数，建议返回的点不使用
//            if ([self.delegate respondsToSelector:@selector(navigationManager:updateLocation:)]) {
//                ADLocationModel *locationModel = [ADLocationModel new];
//                locationModel.suggestType = ADNaviLocationSuggestTypeNotUse;
//                [self.delegate navigationManager:self updateLocation:locationModel];
//            }
//        }
//    }
//}

- (void)stopNavigation
{
//    [self.naviCheckTimer invalidate];
//    self.naviCheckTimer = nil;
    
    [[AMapNaviDriveManager sharedInstance] stopNavi];
}

- (void)adjustShowLocation
{
    self.driveView.showMode = AMapNaviDriveViewShowModeCarPositionLocked;
}

- (void)adjustShowTrafficLayer
{
    self.driveView.showTrafficLayer = !self.driveView.showTrafficLayer;
}
#pragma mark - AMapNaviDriveManagerDelegate,AMapNaviDriveDataRepresentable 方法

// 路径规划成功
- (void)driveManagerOnCalculateRouteSuccess:(AMapNaviDriveManager *)driveManager
{
    //同显相关
    if (driveManager.naviRouteIDs.count) {
        NSUInteger index = driveManager.naviRouteIDs[0].integerValue;
        [driveManager selectNaviRouteWithRouteID:index];
        [driveManager stopNavi];
        
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            self.badAccracyCount = 0;
            self.badAccracyRetryCount = 0;
            if (self.isSimulateNav) {
                [driveManager startEmulatorNavi];
            }else{
                [driveManager startGPSNavi];
            }
        });

    }
    
    if ([self.delegate respondsToSelector:@selector(navigationManager:updateRouteInfo:type:)]) {
        ADNaviRouteInfo *routeInfo = [self naviRoute:driveManager.naviRoute naviInfo:nil currentIndex:0];
        [self.delegate navigationManager:self updateRouteInfo:routeInfo type:ADNavigationRouteTypeAfterCalculate];
    }
}

/**
 *  已经开始导航
 */
- (void)driveManager:(AMapNaviDriveManager *)driveManager didStartNavi:(AMapNaviMode)naviMode
{
    if ([self.delegate respondsToSelector:@selector(navigationManager:updateRouteInfo:type:)]) {
        ADNaviRouteInfo *routeInfo = [self naviRoute:driveManager.naviRoute naviInfo:nil currentIndex:0];
        [self.delegate navigationManager:self updateRouteInfo:routeInfo type:ADNavigationRouteTypeAfterStartNavi];
    }
}

/**
 *  导航信息更新回调
 */
- (void)driveManager:(AMapNaviDriveManager *)driveManager updateNaviInfo:(nullable AMapNaviInfo *)naviInfo
{
    NSInteger currentIndex =  -1;
    
    if (naviInfo.currentSegmentIndex < driveManager.naviRoute.routeSegments.count) {
        AMapNaviSegment *seg = driveManager.naviRoute.routeSegments[naviInfo.currentSegmentIndex];
        if(naviInfo.currentLinkIndex < seg.links.count){
            AMapNaviLink *link =  seg.links[naviInfo.currentLinkIndex];
            if (naviInfo.currentPointIndex < link.coordinates.count) {
                AMapNaviPoint *point = link.coordinates[naviInfo.currentPointIndex];
            
                for (NSInteger i = 0; i < driveManager.naviRoute.routeCoordinates.count; i++) {
                    AMapNaviPoint *p = driveManager.naviRoute.routeCoordinates[i];
                    if ([p isEqualToNaviPoint:point]) {
                        currentIndex = i;
                        break;
                    }
                }
            }
        }
    }
    
    if (naviInfo) {//剩余路程和时间预估
        if ([self.delegate respondsToSelector:@selector(navigationManager:updateRouteInfo:type:)]) {
            ADNaviRouteInfo *routeInfo = [self naviRoute:driveManager.naviRoute naviInfo:naviInfo currentIndex:currentIndex];
            [self.delegate navigationManager:self updateRouteInfo:routeInfo type:ADNavigationRouteTypeRouteUpdate];
        }
    }
}

- (ADNaviRouteInfo *)naviRoute:(AMapNaviRoute *)naviRoute naviInfo:(AMapNaviInfo *)naviInfo currentIndex:(NSInteger)currentIndex
{
    ADNaviRouteInfo *routeInfo = [ADNaviRouteInfo new];
    routeInfo.routeLength = naviRoute.routeLength;
    routeInfo.routeTime = naviRoute.routeTime;
    routeInfo.startLoc = CLLocationCoordinate2DMake(naviRoute.routeStartPoint.latitude, naviRoute.routeStartPoint.longitude);
    routeInfo.endLoc = CLLocationCoordinate2DMake(naviRoute.routeEndPoint.latitude, naviRoute.routeEndPoint.longitude);
    
    NSMutableArray *routePoints = [NSMutableArray array];
    for (int i = 0; i < naviRoute.routeCoordinates.count; i++) {
        AMapNaviPoint *point = naviRoute.routeCoordinates[i];
        ADMinLocationModel *min = [ADMinLocationModel new];
        min.latitude = point.latitude;
        min.longitude = point.latitude;
        [routePoints addObject:min];
    }
    routeInfo.routePoints = routePoints;
    
    routeInfo.routeDriveDistance = naviInfo.routeDriveDistance;
    routeInfo.routeRemainDistance = naviInfo.routeRemainDistance;
    routeInfo.routeRemainTime = naviInfo.routeRemainTime;
    routeInfo.currentPointIndex = currentIndex;
    
    return routeInfo;
}

- (void)driveManager:(AMapNaviDriveManager *)driveManager updateNaviLocation:(nullable AMapNaviLocation *)naviLocation
{
    //返回导航点精度差的处理
    ADNaviLocationSuggestType suggestType = ADNaviLocationSuggestTypeUse;
    if (naviLocation.accuracy > kNaviPointBadAccuracyValue) {//判断为精度差
        suggestType = ADNaviLocationSuggestTypeBestNotUse;
        self.badAccracyCount++;
        if (self.badAccracyCount > kAllowBadAccuracyPointCount) {//超过了允许精度差的个数
            if (self.badAccracyRetryCount < kBadAccuracyPointRetryCount) {//还未超过允许重试次数
                self.badAccracyRetryCount++;
                [driveManager recalculateDriveRouteWithDrivingStrategy:self.naviStrategy];
            }else{//超过了允许重试次数
                suggestType = ADNaviLocationSuggestTypeNotUse;
            }
        }
    }else{//点的精度良好
        self.badAccracyCount = 0;
        self.badAccracyRetryCount = 0;
        suggestType = ADNaviLocationSuggestTypeUse;
    }
    
    self.naviLocationNotUpdateCount = 0;
    if ([self.delegate respondsToSelector:@selector(navigationManager:updateLocation:)]) {
        ADLocationModel *locationModel = [naviLocation locationModel];
        locationModel.suggestType = suggestType;
        [self.delegate navigationManager:self updateLocation:locationModel];
    }
}

/**
 *  模拟导航到达目的地停止导航后的回调函数
 */
- (void)driveManagerDidEndEmulatorNavi:(AMapNaviDriveManager *)driveManager
{
    NSLog(@"已经到达目的地");
}

/**
 *  到达目的地
 */
- (void)driveManagerOnArrivedDestination:(AMapNaviDriveManager *)driveManager
{
    NSLog(@"已经到达目的地");
    if ([self.delegate respondsToSelector:@selector(navigationManager:occurEvent:context:)]) {
        [self.delegate navigationManager:self occurEvent:ADNavigationEventTypeArrived context:@""];
    }
}

/**
 *  发生错误
 */
- (void)driveManager:(AMapNaviDriveManager *)driveManager error:(NSError *)error
{
    NSLog(@"发生错误");
    if ([self.delegate respondsToSelector:@selector(navigationManager:occurError:type:)]) {
        [self.delegate navigationManager:self occurError:error type:ADNavigationErrorTypeStartNavigation];
    }
    [driveManager recalculateDriveRouteWithDrivingStrategy:self.naviStrategy];
}

/**
 *  路径规划失败
 */
- (void)driveManager:(AMapNaviDriveManager *)driveManager onCalculateRouteFailure:(NSError *)error
{
    NSLog(@"路径规划失败");
    if ([self.delegate respondsToSelector:@selector(navigationManager:occurError:type:)]) {
        [self.delegate navigationManager:self occurError:error type:ADNavigationErrorTypeCalculateRoute];
    }
}

/**
 *  路线偏移重新规划路线
 */
- (void)driveManagerNeedRecalculateRouteForYaw:(AMapNaviDriveManager *)driveManager
{
    [driveManager recalculateDriveRouteWithDrivingStrategy:self.naviStrategy];
    if ([self.delegate respondsToSelector:@selector(navigationManager:occurEvent:context:)]) {
        [self.delegate navigationManager:self occurEvent:ADNavigationEventTypeNeedRecalculate context:@""];
    }
}

- (void)driveManager:(AMapNaviDriveManager *)driveManager updateGPSSignalStrength:(AMapNaviGPSSignalStrength)gpsSignalStrength
{
    if ([self.delegate respondsToSelector:@selector(navigationManager:occurEvent:context:)]) {
        NSString *strengehString = nil;
        switch (gpsSignalStrength) {
            case AMapNaviGPSSignalStrengthWeak:
                strengehString = @"弱";
                break;
            case AMapNaviGPSSignalStrengthStrong:
                strengehString = @"强";
                break;
            case AMapNaviGPSSignalStrengthUnknow:
                strengehString = @"未知";
                break;
        }

        [self.delegate navigationManager:self occurEvent:ADNavigationEventTypeGpsSignal context:strengehString];
    }
}

//导航语音
- (void)driveManager:(AMapNaviDriveManager *)driveManager playNaviSoundString:(NSString *)soundString soundStringType:(AMapNaviSoundType)soundStringType
{
    if([self.delegate respondsToSelector:@selector(navigationManagerNeedBroadcastVoice:)]){
        if([self.delegate navigationManagerNeedBroadcastVoice:self]){
//            [[SpeechSynthesizer sharedSpeechSynthesizer] speakString:soundString];
        }
    }
}

- (void)destroySelf
{
    [self stopNavigation];
    [[AMapNaviDriveManager sharedInstance] setDelegate:self];
    [[AMapNaviDriveManager sharedInstance] removeDataRepresentative:self.driveView];
    [[AMapNaviDriveManager sharedInstance] removeDataRepresentative:self];
    [AMapNaviDriveManager destroyInstance];
}


- (BOOL)startFullScreenNavigation
{
    return NO;
}


- (void)mapDidAppearOnView:(nonnull UIView *)aView { 

}


- (void)mapWillAppearOnView:(nonnull UIView *)aView { 
    
}


- (void)mapWillDisappearOnView:(nonnull UIView *)aView { 
    
}


- (void)dealloc
{
    NSLog(@"%@释放了",[self class]);
}

@end

@implementation AMapNaviLocation (LocationModel)
- (ADLocationModel *)locationModel
{
    ADLocationModel *locationModel = [ADLocationModel new];
    locationModel.latitude = self.coordinate.latitude;
    locationModel.longitude = self.coordinate.longitude;
    locationModel.accuracy = self.accuracy;
    locationModel.angle = self.heading;
    locationModel.speed = (self.speed * 1000) / 3600;
    locationModel.time = [self.timestamp timeIntervalSince1970] * 1000;
    locationModel.isMatchNaviPath = self.isMatchNaviPath;
    return locationModel;
}

@end
